﻿/*
 * @Autor: PK
 * @Date: 2021/12/28 10:27:SS
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using O2DESNet;
using ShkSimulation.core.dao.statistic.feature;

namespace ShkSimulation.core.dao {

	public class StatisticOptionProvider {

		public static readonly string DefaultSumValue = "求和";
		public static readonly string DefaultAvgValue = "平均值";
		public static readonly string DefaultTimeAvgValue = "时间平均值";
		
		[ModuleInitializer]
		internal static void DefaultRegister() {
			// 时间统计值,默认注册最后的值
			RegisterTimeStatisticFunction(VariableAndHourStatisticKey.EmptyHourStatisticName, _ => _.LastCount);
			RegisterTimeStatisticFunction(DefaultTimeAvgValue, _ => _.AverageCount);
			// 集合数据统计值,默认注册最终值得 总和 和 平均值
			RegisterNumberStatisticFunction(DefaultSumValue, _ => _.Values.Sum());
			RegisterNumberStatisticFunction(DefaultAvgValue, _ => _.Values.Average());
			// RegisterNumberStatisticFunction("最大吱吱吱", _ => _.Values.Max());
		}
		
		internal static StatisticInfo StatisticSingleData(Dictionary<string/*DataRepoter*/, double> statisticData, string variableName, string timeStatisticName = null) {
			StatisticInfoBuilder builder = new StatisticInfoBuilder()
				.SetVariableName(variableName)
				.SetHourStatisticName(timeStatisticName ?? VariableAndHourStatisticKey.EmptyHourStatisticName);
			foreach (var (key, func) in NumberStatisticExtractFunctions) {
				double value = func(statisticData);
				builder.SetStatisticDataValue(key, value);
			}
			return builder.Build();
		}
		
		internal static List<StatisticInfo> StatisticHourCounter(string variableName, Dictionary<string/*DataRepoterUniqueKey*/, ReadOnlyHourCounter> statisticData) {
			List<StatisticInfo> result = new List<StatisticInfo>();
			foreach (var (key, func) in HourStatisticExtractFunctions) {
				Dictionary<string/*DataRepoterUniqueKey*/, double> value = new Dictionary<string, double>();
				foreach (var (dataReporterKey, readOnlyHourCounter) in statisticData) {
					value.Add(dataReporterKey, func(readOnlyHourCounter));
				}
				// 根据HC统计设置将HC属性转换为一般属性
				StatisticInfo statisticInfo = StatisticSingleData(value, variableName, key);
				result.Add(statisticInfo);
			}
			return result;
		}

		#region 时间统计特性
		private static Dictionary<string /*时间统计特性*/, Func<ReadOnlyHourCounter, double>> HourStatisticExtractFunctions { get; set; } 
			= new Dictionary<string, Func<ReadOnlyHourCounter, double>>();

		public static void RegisterTimeStatisticFunction(string timeStatisticName, Func<ReadOnlyHourCounter, double> func) {
			if (HourStatisticExtractFunctions.ContainsKey(timeStatisticName)) {
				Console.WriteLine($"时间统计特性已存在相同键值:{timeStatisticName}，前值已被覆盖");
				HourStatisticExtractFunctions[timeStatisticName] = func;
			} else {
				HourStatisticExtractFunctions.Add(timeStatisticName, func);
			}
		}
		
		public static void RemoveTimeStatisticFunction(string timeStatisticName) {
			HourStatisticExtractFunctions.Remove(timeStatisticName);
		}
		
		public static void RemoveDefautlTimeStatisticFunctions() {
			HourStatisticExtractFunctions = new Dictionary<string, Func<ReadOnlyHourCounter, double>>();
		}
		#endregion

		#region 集合数据统计特性
		private static Dictionary<string /*集合数据统计特性*/, Func<Dictionary<string/*DataRepoter*/, double>, double>> NumberStatisticExtractFunctions { get; set; } 
			= new Dictionary<string /*集合数据统计特性*/, Func<Dictionary<string/*DataRepoter*/, double>, double>>();

		public static void RegisterNumberStatisticFunction(string statisticName, Func<Dictionary<string/*DataRepoter*/, double>, double> func) {
			if (NumberStatisticExtractFunctions.ContainsKey(statisticName)) {
				Console.WriteLine($"集合数据统计特性已存在相同键值:{statisticName}，前值已被覆盖");
				NumberStatisticExtractFunctions[statisticName] = func;
			} else {
				NumberStatisticExtractFunctions.Add(statisticName, func);
			}
		}
		
		public static void RemoveNumberStatisticFunction(string statisticName) {
			NumberStatisticExtractFunctions.Remove(statisticName);
		}
		
		public static void RemoveDefautlNumberStatisticFunctions() {
			NumberStatisticExtractFunctions = new Dictionary<string, Func<Dictionary<string, double>, double>>();
		}
		#endregion
	}

}